package com.matt.service.impl;

import com.matt.domain.Contract;
import com.matt.domain.ContractProduct;
import com.matt.domain.Product;
import com.matt.domain.statistics.StatPaidContract;
import com.matt.foundation.constant.ContractConstant;
import com.matt.foundation.constant.ProductConstant;

import com.matt.foundation.utils.DateUtil;
import com.matt.remoteCall.SsoCallService;
import com.matt.repository.ContractProductRepository;
import com.matt.repository.ContractRepository;
import com.matt.repository.ProductRepository;
import com.matt.repository.statictics.StatPaidContractRepository;
import com.matt.service.*;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.matt.foundation.constant.AnalysisConstant.CONTRACT_PRODUCT_RENEWAL;
import static com.matt.foundation.constant.AnalysisConstant.NORMAL_STOP;


/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2018/7/31
 * *******************************
 */
@Service
@Slf4j
public class SchedulerPlanServiceImpl implements SchedulerPlanService {

    @Autowired
    private ContractRepository contractRepository;

    @Autowired
    private ContractProductRepository contractProductRepository;

    @Autowired
    private ContractService contractService;

    @Autowired
    private AnalysisService analysisService;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private StatPaidContractRepository statPaidContractRepository;

    @Override
    public void generateRenewalClientele(Date date) {
        List<Contract> normalContractList = contractRepository.findByStatus(ContractConstant.Status.NORMAL.codeOf());
        for (Contract contract : normalContractList) {
            if (DateUtil.betweenDays(contract.getEndDate(), date)<0)
                continue;
            List<ContractProduct> products = contractProductRepository.findByContractId(contract.getId());
            for (ContractProduct product : products) {
                if (product.getProductType() == ProductConstant.NURSERY && DateUtil.betweenDays(contract.getEndDate(), date) <= 30 && DateUtil.betweenDays(contract.getEndDate(), date) > 0) {
                    //生成托班待续约客户
                    analysisService.createNeedRenewalClientele(contract.getClienteleId(), contract.getId(), ProductConstant.NURSERY, false, contract.getAreaId());
                    //生成续单可预计收入
                    analysisService.createExpectIncome(product.getClienteleId(), contract.getId(), product.getStandardTotalAmount(), CONTRACT_PRODUCT_RENEWAL, product.getType(), contract.getAreaId(), date);
                } else if (product.getProductType() == ProductConstant.EARLY && product.getRemainCount() <= 8 && product.getRemainCount() > 0) {
                    //生成早教待续约客户
                    analysisService.createNeedRenewalClientele(contract.getClienteleId(), contract.getId(), ProductConstant.EARLY, false, contract.getAreaId());
                    //生成续单可预计收入
                    analysisService.createExpectIncome(product.getClienteleId(), contract.getId(), product.getStandardTotalAmount(), CONTRACT_PRODUCT_RENEWAL, product.getType(), contract.getAreaId(), date);
                }
            }
        }
    }

    @Transactional
    @Override
    public void beginContract(Date date) {
        //修改合同状态
        List<Contract> nonStartContractList = contractRepository.findByStatus(ContractConstant.Status.NON_START.codeOf());
        for (Contract contract : nonStartContractList){
            if (contract.getBeginDate().compareTo(date) <=0){
                contract.setStatus(ContractConstant.Status.NORMAL.codeOf());
                contract.setStatusVal(ContractConstant.Status.NORMAL.valueOf());
                contractRepository.save(contract);
                //处理教务系统逻辑
                contractService.beginTeachRoll(contract);
            }else{
                System.out.println("now date " + date + " before contract begint date :" + contract.getId() + " code:" + contract.getCode());
            }
        }
    }

    @Override
    public void endContract(Date date) {
        List<Contract> normalContractList = contractRepository.findByStatus(ContractConstant.Status.NORMAL.codeOf());
        for (Contract contract : normalContractList) {
            if (contract.getEndDate().compareTo(date) < 0) {
                contractService.end(contract);
//                log.info("end contract : contractId:[{}], clienteleId:[{}] ", contract.getId(), contract.getClienteleId());
                //处理教务系统逻辑
                contractService.endTeachRoll(contract, "");
                //处理经营系统逻辑
                analysisService.createEndClient(contract.getClienteleId(), NORMAL_STOP, contract.getAreaId(), date);
            }
        }
    }

    @Override
    public void generateStatPaidContract(Date date) {
        //计算产品客单价
        //FIXME 待优化
//        List<AreaDTO> areaDTOList = ssoCallService.getAllArea();
//        Page<Product> findAllByDeletedIsFalseAndIsVisibleTrueOrderByCreatedDesc(Pageable pageable);
//
//
//        for (AreaDTO area : areaDTOList) {
//            List<Product> products = productRepository.findByAreaIdAndDeletedIsFalseAndIsVisible(area.getId(), 1);
//
//            log.info("analyze paid contract ::: area {} with products {}", area.getName(), products.size());
//
//            List<Contract> contracts = contractRepository.findByPayStatusAndPaidDateBeforeAndAreaIdAndFromChannelNot(ContractConstant.PayStatus.PAID.codeOf(), date, area.getId(), 0);
//            Date yesterday = new Date(DateUtil.plusDays(date.getTime(), -1L));
//            generatePaidContract(contracts, products, area.getId(), yesterday);
//        }
    }

    private void generatePaidContract(List<Contract> contractList, List<Product> products, String areaId, Date date) {
        List<StatPaidContract> paidContractList = Lists.newArrayList();
        paidContractList.add(StatPaidContract.of("0","总和", areaId, date));
        for (Product product:products){
            paidContractList.add(StatPaidContract.of(product.getId(), product.getName(), areaId, date));
        }
        for (Contract contract : contractList) {
            fillTotalCount(paidContractList, contract);
            List<ContractProduct> productList = contractProductRepository.findByContractId(contract.getId());
            for (ContractProduct product : productList) {
                fillProductCount(paidContractList, product);
            }
        }
        updatePaidContractList(paidContractList, areaId, date);
    }

    private void fillProductCount(List<StatPaidContract> paidContractList, ContractProduct product) {
        for (StatPaidContract paidContract:paidContractList){
            if (paidContract.getProductId().equals(product.getProductId())){
                paidContract.setTotalAmount(paidContract.getTotalAmount().add(product.getPracticalTotalAmount()));
                paidContract.setProductId(product.getProductId());
                paidContract.setCount(paidContract.getCount() + product.getCount());
                paidContract.refreshUnitPrice();
            }
        }
    }

    private void fillTotalCount(List<StatPaidContract> paidContractList, Contract contract) {
        for (StatPaidContract paidContract:paidContractList){
            if (paidContract.getProductId().equals("0")) {
                paidContract.setCount(paidContract.getCount() + 1);
                paidContract.setProductId("0");
                paidContract.setTotalAmount(paidContract.getTotalAmount());
                paidContract.refreshUnitPrice();
            }
        }
    }

    private void updatePaidContractList(List<StatPaidContract> paidContractList, String areaId, Date date){
        String yesterdayStr = DateUtil.millisToDateTime(date.getTime(), "yyyy-MM-dd");
        Date begin = DateUtil.getCurrentDayBeginAndEnd(yesterdayStr).get("beg");
        Date emd = DateUtil.getCurrentDayBeginAndEnd(yesterdayStr).get("end");
        for (StatPaidContract paidContract: paidContractList){
            StatPaidContract newContract = statPaidContractRepository.findByAreaIdAndProductIdAndCreatedBetween(areaId, paidContract.getProductId(), begin, emd);
            if (Objects.nonNull(newContract)){
                newContract.setCreated(date);
                newContract.setTotalAmount(paidContract.getTotalAmount());
                newContract.setCount(paidContract.getCount());
                newContract.refreshUnitPrice();
                statPaidContractRepository.save(newContract);
            }else{
                statPaidContractRepository.save(paidContract);
            }
        }
    }
}
